package com.itheima.netty;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.itheima.config.ApplicationContextProvider;
import com.itheima.entity.Result;
import com.itheima.entity.StatusCode;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;

import java.util.HashMap;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

/**
 *  1.需要知道用户是否进行连接(连接8000端口)
 *  2.当用户进行连接后，获取到客户端连接传送的userid值，根据id值到消息队列中获取对应的队列
 *  3.获取队列中的消息
 *  4.将消息用websocket写给用户
 */
public class MyWebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
    //springmvc提供用于json解析和转换
    private static ObjectMapper objectMapper = new ObjectMapper();
    //从spring容器中获取简单消息监听容器
    public static SimpleMessageListenerContainer sysNoticeContainer =
            (SimpleMessageListenerContainer) ApplicationContextProvider.getApplicationContext()
                    .getBean("sysNoticeContainer");
    //从spring容器中获取简单消息监听容器 点赞消息队列
    public static SimpleMessageListenerContainer userNoticeListener =
            (SimpleMessageListenerContainer) ApplicationContextProvider.getApplicationContext()
                    .getBean("userNoticeListener");
    RabbitTemplate rabbitTemplate = ApplicationContextProvider.getApplicationContext()
            .getBean(RabbitTemplate.class);
    //创建一个存放用户连接的集合
    public static ConcurrentHashMap<String, Channel> userChannelMap = new ConcurrentHashMap<>();
    @Override
    public void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception {
        //获取用户连接时传送的数据 格式为{"userId":"1"}
        String text = textWebSocketFrame.text();
        //将获取到的json数据进行解析
        String userId = objectMapper.readTree(text).get("userId").asText();
        //根据获取到的用户id从容器中获取相对应的连接通道
        Channel channel = userChannelMap.get(userId);
        //判断连接是否存在
        if(channel==null){
          //容器如果获取不到的话就代表第一次连接
            channel = channelHandlerContext.channel();
            userChannelMap.put(userId,channel);
        }
        //个根据获取到的用户id，从消息队列中获取对应的队列
        RabbitAdmin rabbitAdmin = new RabbitAdmin(rabbitTemplate);
        //拼接队列名称  订阅队列
        String queueName = "tensquare_queue_"+userId;
        //拼接队列名称  点赞队列
        String queueNameThumbup = "thumbup_queue_"+userId;
        //消息订阅数量
        int noticeCount = 0;
        //消息点赞数量
        int userNoticeCount = 0;
        //获取队列
        Properties queueProperties = rabbitAdmin.getQueueProperties(queueName);
        if(queueProperties!=null){
            //如果队列不为空
            noticeCount = (int)queueProperties.get("QUEUE_MESSAGE_COUNT");
        }
        //获取点赞队列
        Properties queueProperties1 = rabbitAdmin.getQueueProperties(queueNameThumbup);
        if(queueProperties1!=null){
            //如果队列不为空
            userNoticeCount = (int)queueProperties1.get("QUEUE_MESSAGE_COUNT");
        }
        //封装返回的数据  订阅数据
        HashMap countMap = new HashMap();
        countMap.put("sysNoticeCount", noticeCount);
        Result result = new Result(true, StatusCode.OK,"查询成功",countMap);
        //封装返回的数据  点赞数据
        HashMap countMap1 = new HashMap();
        countMap.put("userNoticeCount", userNoticeCount);
        Result result1 = new Result(true, StatusCode.OK,"查询成功",countMap1);
        //将返回数据通过websockt回写给用户
        channel.writeAndFlush(new TextWebSocketFrame(objectMapper.writeValueAsString(result)));
        channel.writeAndFlush(new TextWebSocketFrame(objectMapper.writeValueAsString(result1)));
        //消费完消息后清除
        if(noticeCount>0){
            rabbitAdmin.purgeQueue(queueName,true);
        }
        //消费完消息后清除
        if(userNoticeCount>0){
            rabbitAdmin.purgeQueue(queueNameThumbup,true);
        }
        //监听消息订阅的队列，可以主动推送消息
        sysNoticeContainer.addQueueNames(queueName);
        userNoticeListener.addQueueNames(queueNameThumbup);
    }
}
